//
//C12880MA Spectrometer 18G00871
//
#include <M5Stack.h>
#include <driver/adc.h>
#include <esp_adc_cal.h>
#include <math.h>

//波長補正係数 A0+B1*pix+B2*pix^2+B3*pix^3+B4*pix4+B5*pix^5
const double pA0 = 3.098182303e2;
const double pB1 = 2.734323571;
const double pB2 =-1.647768389e-3;
const double pB3 =-4.018691578e-6;
const double pB4 =-3.208813535e-9;
const double pB5 = 2.091379510e-11;

bool clear = 1; //Screen clear flag
bool test = 0; //Acquisition(取得)flag
int plot_switch = 0; //Line color
const int COLOR_SELECT = 4;
const unsigned short PLOT_COLORS[COLOR_SELECT] = {TFT_BLACK,TFT_GREEN,TFT_RED,TFT_BLUE};
int gain = 0; //clock_width control
const int CLOCK_SELECT = 6;
const int CLOCK_WIDTH[CLOCK_SELECT] = {1,5,10,50,100,500};

struct{ //Screen public class
typedef struct {unsigned short ox,oy,wx,hy,tx,ty;}Axis;
const Axis Plot = {40,10,280,200,20,20}; //Screen size 320*240
short x,y,px,py;
float X_Div,V_Div;

void init(float X_Div_i,float V_Div_i){ //画面初期化
X_Div = X_Div_i; //
V_Div = V_Div_i;
M5.Lcd.fillScreen(TFT_WHITE);
M5.Lcd.fillRect(Plot.ox,Plot.oy,Plot.wx,Plot.hy,TFT_YELLOW); //Screen background color
for(int i=Plot.ox; i <= (Plot.ox+Plot.wx); i+=Plot.tx){ //Y軸グリッド
M5.Lcd.drawLine(i,Plot.oy,i,Plot.oy+Plot.hy,TFT_WHITE);
}
for(int i=Plot.oy; i <= (Plot.oy+Plot.hy); i+=Plot.ty){ //X軸グリッド
M5.Lcd.drawLine(Plot.ox,i,Plot.ox+Plot.wx,i,TFT_WHITE);
}
M5.Lcd.setCursor(1,Plot.hy/2); //Y軸単位文字の位置
M5.Lcd.setTextSize(2); //文字サイズ
M5.Lcd.printf("V"); //V(電圧)
M5.Lcd.setCursor(Plot.wx/2+20,Plot.hy+23); //X軸単位文字の位置
M5.Lcd.printf("nm"); //nm(ナノメートル)
M5.Lcd.setTextSize(1);
M5.Lcd.setTextColor(BLACK);
for(int yaxis = 0; yaxis<=Plot.hy/Plot.ty; yaxis+=2){ //Y軸目盛
M5.Lcd.setCursor(10,Plot.hy+5-yaxis*Plot.ty);
M5.Lcd.printf("%2.1f",yaxis*V_Div);
}
for(int pix_count=0; pix_count<Plot.wx; pix_count+=(Plot.tx*2)){ //X軸目盛
float pix = (float)pix_count; //ピクセルと波長の関係の計算
float wavelength = pA0 +pB1*pix +pB2*pow(pix,2) +pB3*pow(pix,3) +pB4*pow(pix,4) +pB5*pow(pix,5);
M5.Lcd.setCursor(Plot.ox+pix_count-10,Plot.hy+15); //-8: X offset,15: Y offset
M5.Lcd.printf("%d",(int)(wavelength+0.5)); //波長描画
}
} //init(初期化)
void line(float h,float v,bool start_flag,unsigned short color){ //線分描画
y = Plot.oy+Plot.hy-(short)(v*(float)Plot.ty/V_Div);
x = Plot.ox+(short)(h*(float)Plot.tx/X_Div);
if((!start_flag) & (y>0)){
M5.Lcd.drawLine(px,py,x,y,color);
M5.Lcd.drawLine(px,py+1,x,y+1,color);
}
px=x; py=y;
} //line(線引き)
void plot_value(int x_i,int y_i,char *p,int in1){ //文字列と数値の表示
M5.Lcd.setCursor(x_i,y_i);
M5.Lcd.printf("%s %d\n",p,in1);
}
} Screen;
//-----------------------
void setup() {
M5.begin();
pinMode(16,OUTPUT); //R2 clock 出力
pinMode(17,OUTPUT); //T2 STrobe 出力
pinMode(2,INPUT); //G2 EOS 入力(未使用)
pinMode(5,INPUT); //G5 TRG 入力(未使用)
}

void loop() {
if(M5.BtnC.wasPressed()){clear=1;} // 右ボタンで 画面クリア
if(M5.BtnB.wasPressed()){test=1;} // 中央ボタンで 計測
if(M5.BtnA.wasPressed()){
gain++;
if(gain>=CLOCK_SELECT) gain=0; // 左ボタンでゲインの切り替え
Screen.plot_value(250,30,"Gain",gain);
}
if(clear){ //画面クリア
Screen.init(20.0,0.2); //X:20/div Y:0.2/div
M5.Lcd.setCursor(0,0);
M5.Lcd.setTextSize(1);
M5.Lcd.setTextColor(BLACK);
Screen.plot_value(250,30,"Gain",gain);
clear=0;
}
if(test){ //測定
const int Pix_total = 288; // C12880MA の画素数
const int Strobe_width = 6; // STrobe信号の幅
const int Video_out_delay = 87; // ビデオ出力開始のクロック数
bool start_flag = 1; //line描画の 始点フラグ
int pix_count = 0; //ピクセルカウンタ
for(int ck=0; ck<(Pix_total+Strobe_width+Video_out_delay); ck++){ //クロックループ
bool trig_flag = 0;//Clear
for(int ii=0; ii<CLOCK_WIDTH[gain]; ii++){ //クロックH幅ループ
digitalWrite(16,1); //R2 clock H出力
}
digitalWrite(16,0); //R2 clock L出力
int ad_in = analogRead(36); //ADコンバーター入力
bool strobe_out = (ck<(Strobe_width))?1:0; //STrobe信号作成
digitalWrite(17,strobe_out); //T2 STrobe信号出力
for(int ii=0; ii<CLOCK_WIDTH[gain]; ii++){ //クロックL幅ループ
digitalWrite(16,0); //R2 clock L出力
}
if(ck>(Strobe_width+Video_out_delay)){
if(pix_count < Pix_total){
float Vil = (3.3/4096.0*(((float)ad_in) + 0.14)/0.965); //ADコンバーターの誤差補正
unsigned short color = PLOT_COLORS[ plot_switch ];
Screen.line(float(pix_count),Vil,start_flag,color); //グラフ描画
start_flag = 0; //line描画の始点フラグをクリア
}
pix_count ++;
}
}
plot_switch++; //グラフの色の切り替え
if(plot_switch>=COLOR_SELECT) plot_switch=0;
test = 0;
}
M5.update();
}




                戻る